home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Extra 1996 #3 / AmigaPlus_CD-ROM-EXTRA_Nr.3.bin / aminet-spiele / role on / larn / scores.c < prev    next >
C/C++ Source or Header  |  1997-12-31  |  26KB  |  710 lines

  1. /* scores.c
  2.  *
  3.  *  readboard()     Function to read in the scoreboard into a static buffer
  4.  *  writeboard()    Function to write the scoreboard from readboard()'s buffer
  5.  *  makeboard()     Function to create a new scoreboard (wipe out old one)
  6.  *  hashewon()   Function to return 1 if player has won a game before, else 0
  7.  *  long paytaxes(x)     Function to pay taxes if any are due
  8.  *  winshou()       Subroutine to print out the winning scoreboard
  9.  *  shou(x)         Subroutine to print out the non-winners scoreboard
  10.  *  showscores()        Function to show the scoreboard on the terminal
  11.  *  showallscores() Function to show scores and the iven lists that go with them
  12.  *  sortboard()     Function to sort the scoreboard
  13.  *  newscore(score, whoo, whyded, winner)   Function to add entry to scoreboard
  14.  *  new1sub(score,i,whoo,taxes)           Subroutine to put player into a
  15.  *  new2sub(score,i,whoo,whyded)          Subroutine to put player into a
  16.  *  died(x)     Subroutine to record who played larn, and what the score was
  17.  *  diedsub(x) Subroutine to print out a line showing player when he is killed
  18.  *  diedlog()   Subroutine to read a log file and print it out in ascii format
  19.  *  getplid(name)       Function to get players id # from id file
  20.  */
  21. #ifdef VMS
  22. # include <types.h>
  23. # include <stat.h>
  24. #else
  25. # include <sys/types.h>
  26. # ifndef MSDOS
  27. #  ifndef AMIGA
  28. #   include <sys/times.h>
  29. #  endif AMIGA
  30. # endif MSDOS
  31. # include <sys/stat.h>
  32. #endif
  33. #include "header.h"
  34. #include "larndefs.h"
  35. #include "monsters.h"
  36. #include "objects.h"
  37. #include "player.h"
  38.  
  39. struct scofmt           /*  This is the structure for the scoreboard        */
  40.     {
  41.     long score;         /* the score of the player                          */
  42.     long suid;          /* the user id number of the player                 */
  43.     short what;         /* the number of the monster that killed player     */
  44.     short level;        /* the level player was on when he died             */
  45.     short hardlev;      /* the level of difficulty player played at         */
  46.     short order;        /* the relative ordering place of this entry        */
  47.     char who[40];       /* the name of the character                        */
  48.     char sciv[26][2];   /* this is the inventory list of the character      */
  49.     };
  50. struct wscofmt          /* This is the structure for the winning scoreboard */
  51.     {
  52.     long score;         /* the score of the player                          */
  53.     long timeused;      /* the time used in mobuls to win the game          */
  54.     long taxes;         /* taxes he owes to LRS                             */
  55.     long suid;          /* the user id number of the player                 */
  56.     short hardlev;      /* the level of difficulty player played at         */
  57.     short order;        /* the relative ordering place of this entry        */
  58. # ifndef MAIL           /* dgk */
  59.     char hasmail;       /* 1 if mail is to be read, 0 otherwise */
  60. # endif
  61.     char who[40];       /* the name of the character                        */
  62.     };
  63.  
  64. struct log_fmt          /* 102 bytes struct for the log file                */
  65.     {
  66.     long score;         /* the players score                                */
  67.     long diedtime;      /* time when game was over                          */
  68.     short cavelev;      /* level in caves                                   */
  69.     short diff;         /* difficulty player played at                      */
  70. #ifdef EXTRA
  71.     long elapsedtime;   /* real time of game in seconds                     */
  72.     long bytout;        /* bytes input and output                           */
  73.     long bytin;
  74.     long moves;         /* number of moves made by player                   */
  75.     short ac;           /* armor class of player                            */
  76.     short hp,hpmax;     /* players hitpoints                                */
  77.     short cputime;      /* cpu time needed in seconds                       */
  78.     short killed,spused;/* monsters killed and spells cast                  */
  79.     short usage;        /* usage of the cpu in %                            */
  80.     short lev;          /* player level                                     */
  81. #endif
  82.     char who[12];       /* player name                                      */
  83.     char what[46];      /* what happened to player                          */
  84.     };
  85.  
  86. static struct scofmt sco[SCORESIZE];    /* the structure for the scoreboard  */
  87. static struct wscofmt winr[SCORESIZE];  /* struct for the winning scoreboard */
  88. static struct log_fmt logg;             /* structure for the log file        */
  89. static char *whydead[] = {
  90.     "quit", "suspended", "self - annihilated", "shot by an arrow",
  91.     "hit by a dart", "fell into a pit", "fell into a bottomless pit",
  92.     "a winner", "trapped in solid rock", "killed by a missing save file",
  93.     "killed by an old save file", "caught by the greedy cheater checker trap",
  94.     "killed by a protected save file","killed his family and committed suicide",
  95.     "erased by a wayward finger", "fell through a bottomless trap door",
  96.     "fell through a trap door", "drank some poisonous water",
  97.     "fried by an electric shock", "slipped on a volcano shaft",
  98.     "killed by a stupid act of frustration", "attacked by a revolting demon",
  99.     "hit by his own magic", "demolished by an unseen attacker",
  100.     "fell into the dreadful sleep", "killed by an exploding chest",
  101. /*26*/  "killed by a missing maze data file", "annihilated in a sphere",
  102.     "died a post mortem death","wasted by a malloc() failure"
  103.     };
  104.  
  105.  
  106. /*
  107.  *  readboard()     Function to read in the scoreboard into a static buffer
  108.  *
  109.  *  returns -1 if unable to read in the scoreboard, returns 0 if all is OK
  110.  */
  111. static readboard()
  112.     {
  113.     if (lopen(scorefile)<0)
  114.       { lprcat("Can't read scoreboard\n"); lflush(); return(-1); }
  115.     lrfill((char*)sco,sizeof(sco));     lrfill((char*)winr,sizeof(winr));
  116.     lrclose();  lcreat((char*)0);  return(0);
  117.     }
  118.  
  119. /*
  120.  *  writeboard()    Function to write the scoreboard from readboard()'s buffer
  121.  *
  122.  *  returns -1 if unable to write the scoreboard, returns 0 if all is OK
  123.  */
  124. static writeboard()
  125.     {
  126.     set_score_output();
  127.     if (lcreat(scorefile)<0)
  128.       { lprcat("Can't write scoreboard\n"); lflush(); return(-1); }
  129.     lwrite((char*)sco,sizeof(sco));     lwrite((char*)winr,sizeof(winr));
  130.     lwclose();  lcreat((char*)0);  return(0);
  131.     }
  132.  
  133. /*
  134.  *  makeboard()         Function to create a new scoreboard (wipe out old one)
  135.  *
  136.  *  returns -1 if unable to write the scoreboard, returns 0 if all is OK
  137.  */
  138. makeboard()
  139.     {
  140.     register int i;
  141.     for (i=0; i<SCORESIZE; i++)
  142.         {
  143.         winr[i].taxes = winr[i].score = sco[i].score = 0;
  144.         winr[i].order = sco[i].order = i;
  145.         }
  146.     if (writeboard()) return(-1);
  147.     chmod(scorefile,0666);
  148.     return(0);
  149.     }
  150.  
  151. /*
  152.  *  hashewon()   Function to return 1 if player has won a game before, else 0
  153.  *
  154.  *  This function also sets c[HARDGAME] to appropriate value -- 0 if not a
  155.  *  winner, otherwise the next level of difficulty listed in the winners
  156.  *  scoreboard.  This function also sets outstanding_taxes to the value in
  157.  *  the winners scoreboard.
  158.  */
  159. hashewon()
  160.     {
  161.     register int i;
  162.     c[HARDGAME] = 0;
  163.     if (readboard() < 0) return(0); /* can't find scoreboard */
  164.     for (i=0; i<SCORESIZE; i++) /* search through winners scoreboard */
  165.        if (winr[i].suid == userid)
  166.           if (winr[i].score > 0)
  167.             {
  168.             c[HARDGAME]=winr[i].hardlev+1;  outstanding_taxes=winr[i].taxes;
  169.             return(1);
  170.             }
  171.     return(0);
  172.     }
  173.  
  174. # ifndef MAIL           /* dgk */
  175. checkmail()
  176. {
  177.     register int    i;
  178.     long        gold, taxes;
  179.  
  180.     if (readboard() < 0)
  181.         return;         /* can't find scoreboard */
  182.     for (i = 0; i < SCORESIZE; i++) /* search through winners scoreboard */
  183.         if (winr[i].suid == userid
  184.         &&  winr[i].score > 0
  185.         &&  winr[i].hasmail) {
  186.             winr[i].hasmail = 0;
  187.             gold = taxes = winr[i].taxes;
  188.             writeboard();
  189.  
  190.             /* Intuit the amount of gold -- should have changed
  191.              * the score file, but ...  TAXRATE is an fraction.
  192.              */
  193.             while ((gold * TAXRATE) < taxes)
  194.                 gold += taxes;
  195.             readmail(gold);
  196.         }
  197. }
  198. # endif
  199.  
  200.  
  201. /*
  202.  *  long paytaxes(x)         Function to pay taxes if any are due
  203.  *
  204.  *  Enter with the amount (in gp) to pay on the taxes.
  205.  *  Returns amount actually paid.
  206.  */
  207. long paytaxes(x)
  208.     long x;
  209.     {
  210.     register int i;
  211.     register long amt;
  212.     if (x<0) return(0L);
  213.     if (readboard()<0) return(0L);
  214.     for (i=0; i<SCORESIZE; i++)
  215.         if (winr[i].suid == userid) /* look for players winning entry */
  216.             if (winr[i].score>0) /* search for a winning entry for the player */
  217.                 {
  218.                 amt = winr[i].taxes;
  219.                 if (x < amt) amt=x;     /* don't overpay taxes (Ughhhhh) */
  220.                 winr[i].taxes -= amt;
  221.                 outstanding_taxes -= amt;
  222.                 if (writeboard()<0) return(0);
  223.                 return(amt);
  224.                 }
  225.     return(0L); /* couldn't find user on winning scoreboard */
  226.     }
  227.  
  228. /*
  229.  *  winshou()       Subroutine to print out the winning scoreboard
  230.  *
  231.  *  Returns the number of players on scoreboard that were shown 
  232.  */
  233. static winshou()
  234.     {
  235.     register struct wscofmt *p;
  236.     register int i,j,count;
  237.     for (count=j=i=0; i<SCORESIZE; i++) /* is there anyone on the scoreboard? */
  238.         if (winr[i].score != 0)
  239.             { j++; break; }
  240.     if (j)
  241.         {
  242.         lprcat("\n  Score    Difficulty   Time Needed   Larn Winners List\n");
  243.  
  244.         for (i=0; i<SCORESIZE; i++) /* this loop is needed to print out the */
  245.           for (j=0; j<SCORESIZE; j++) /* winners in order */
  246.             {
  247.             p = &winr[j];   /* pointer to the scoreboard entry */
  248.             if (p->order == i)
  249.                 {
  250.                 if (p->score)
  251.                     {
  252.                     count++;
  253.                     lprintf("%10d     %2d      %5d Mobuls   %s \n",
  254.                     (long)p->score,(long)p->hardlev,(long)p->timeused,p->who);
  255.                     }
  256.                 break;
  257.                 }
  258.             }
  259.         }
  260.     return(count);  /* return number of people on scoreboard */
  261.     }
  262.  
  263. /*
  264.  *  shou(x)         Subroutine to print out the non-winners scoreboard
  265.  *      int x;
  266.  *
  267.  *  Enter with 0 to list the scores, enter with 1 to list inventories too
  268.  *  Returns the number of players on scoreboard that were shown 
  269.  */
  270. static shou(x)
  271.     int x;
  272.     {
  273.     register int i,j,n,k;
  274.     int count;
  275.     for (count=j=i=0; i<SCORESIZE; i++) /* is the scoreboard empty? */
  276.         if (sco[i].score!= 0)
  277.             { j++; break; }
  278.     if (j)
  279.         {
  280.         lprcat("\n   Score   Difficulty   Larn Visitor Log\n");
  281.         for (i=0; i<SCORESIZE; i++) /* be sure to print them out in order */
  282.           for (j=0; j<SCORESIZE; j++)
  283.             if (sco[j].order == i)
  284.                 {
  285.                 if (sco[j].score)
  286.                     {
  287.                     count++;
  288.                     lprintf("%10d     %2d       %s ",
  289.                         (long)sco[j].score,(long)sco[j].hardlev,sco[j].who);
  290.                     if (sco[j].what < 256) lprintf("killed by a %s",monster[sco[j].what].name);
  291.                         else lprintf("%s",whydead[sco[j].what - 256]);
  292.                     if (x != 263) lprintf(" on %s",levelname[sco[j].level]);
  293.                     if (x)
  294.                         {
  295.                         for (n=0; n<26; n++) { iven[n]=sco[j].sciv[n][0]; ivenarg[n]=sco[j].sciv[n][1]; }
  296.                         for (k=1; k<99; k++)
  297.                           for (n=0; n<26; n++)
  298.                             if (k==iven[n]) show3(n);
  299.                         lprcat("\n\n");
  300.                         }
  301.                     else lprc('\n');
  302.                     }
  303.                 j=SCORESIZE;
  304.                 }
  305.         }
  306.     return(count);  /* return the number of players just shown */
  307.     }
  308.  
  309. /*
  310.  *  showscores()        Function to show the scoreboard on the terminal
  311.  *
  312.  *  Returns nothing of value
  313.  */
  314. static char esb[] = "The scoreboard is empty.\n";
  315. showscores()
  316.     {
  317.     register int i,j;
  318.     lflush();  lcreat((char*)0);  if (readboard()<0) return;
  319.     i=winshou();    j=shou(0);
  320.     if (i+j == 0) lprcat(esb); else lprc('\n');
  321.     lflush();
  322.     }
  323.  
  324. /*
  325.  *  showallscores() Function to show scores and the iven lists that go with them
  326.  *
  327.  *  Returns nothing of value
  328.  */
  329. showallscores()
  330.     {
  331.     register int i,j;
  332.     lflush();  lcreat((char*)0);  if (readboard()<0) return;
  333.     c[WEAR] = c[WIELD] = c[SHIELD] = -1;  /* not wielding or wearing anything */
  334.     for (i=0; i<MAXPOTION; i++) potionname[i][0]=' ';
  335.     for (i=0; i<MAXSCROLL; i++) scrollname[i][0]=' ';
  336.     i=winshou();  j=shou(1);
  337.     if (i+j==0) lprcat(esb); else lprc('\n');
  338.     lflush();
  339.     }
  340.  
  341. /*
  342.  *  sortboard()     Function to sort the scoreboard
  343.  *
  344.  *  Returns 0 if no sorting done, else returns 1
  345.  */
  346. static sortboard()
  347.     {
  348.     register int i,j,pos;
  349.     long jdat;
  350.     for (i=0; i<SCORESIZE; i++) sco[i].order = winr[i].order = -1;
  351.     pos=0;  while (pos < SCORESIZE)
  352.         {
  353.         jdat=0;
  354.         for (i=0; i<SCORESIZE; i++)
  355.             if ((sco[i].order < 0) && (sco[i].score >= jdat))
  356.                 { j=i;  jdat=sco[i].score; }
  357.         sco[j].order = pos++;
  358.         }
  359.     pos=0;  while (pos < SCORESIZE)
  360.         {
  361.         jdat=0;
  362.         for (i=0; i<SCORESIZE; i++)
  363.             if ((winr[i].order < 0) && (winr[i].score >= jdat))
  364.                 { j=i;  jdat=winr[i].score; }
  365.         winr[j].order = pos++;
  366.         }
  367.     return(1);
  368.     }
  369.  
  370. /*
  371.  *  newscore(score, whoo, whyded, winner)   Function to add entry to scoreboard
  372.  *      int score, winner, whyded;
  373.  *      char *whoo;
  374.  *
  375.  *  Enter with the total score in gp in score,  players name in whoo,
  376.  *      died() reason # in whyded, and TRUE/FALSE in winner if a winner
  377.  *  ex.     newscore(1000, "player 1", 32, 0);
  378.  */
  379. static newscore(score, whoo, whyded, winner)
  380.     long score;
  381.     int winner, whyded;
  382.     char *whoo;
  383.     {
  384.     register int i;
  385.     long taxes;
  386.     if (readboard() < 0) return;    /*  do the scoreboard   */
  387.     /* if a winner then delete all non-winning scores */
  388.     if (cheat) winner=0;    /* if he cheated, don't let him win */
  389.     if (winner)
  390.         {
  391.         for (i=0; i<SCORESIZE; i++) if (sco[i].suid == userid) sco[i].score=0;
  392.         taxes = score*TAXRATE;
  393.         score += 100000*c[HARDGAME];    /* bonus for winning */
  394.     /* if he has a slot on the winning scoreboard update it if greater score */
  395.         for (i=0; i<SCORESIZE; i++) if (winr[i].suid == userid)
  396.                 { new1sub(score,i,whoo,taxes); return; }
  397.     /* he had no entry. look for last entry and see if he has a greater score */
  398.         for (i=0; i<SCORESIZE; i++) if (winr[i].order == SCORESIZE-1)
  399.                 { new1sub(score,i,whoo,taxes); return; }
  400.         }
  401.     else if (!cheat) /* for not winning scoreboard */
  402.         {
  403.     /* if he has a slot on the scoreboard update it if greater score */
  404.         for (i=0; i<SCORESIZE; i++) if (sco[i].suid == userid)
  405.                 { new2sub(score,i,whoo,whyded); return; }
  406.     /* he had no entry. look for last entry and see if he has a greater score */
  407.         for (i=0; i<SCORESIZE; i++) if (sco[i].order == SCORESIZE-1)
  408.                 { new2sub(score,i,whoo,whyded); return; }
  409.         }
  410.     }
  411.  
  412. /*
  413.  *  new1sub(score,i,whoo,taxes)       Subroutine to put player into a 
  414.  *      int score,i,whyded,taxes;         winning scoreboard entry if his score
  415.  *      char *whoo;                       is high enough
  416.  *
  417.  *  Enter with the total score in gp in score,  players name in whoo,
  418.  *      died() reason # in whyded, and TRUE/FALSE in winner if a winner
  419.  *      slot in scoreboard in i, and the tax bill in taxes.
  420.  *  Returns nothing of value
  421.  */
  422. static new1sub(score,i,whoo,taxes)
  423.     long score,taxes;
  424.     int i;
  425.     char *whoo;
  426.     {
  427.     register struct wscofmt *p;
  428.     p = &winr[i];
  429.     p->taxes += taxes;
  430.     if ((score >= p->score) || (c[HARDGAME] > p->hardlev))
  431.         {
  432.         strcpy(p->who,whoo);        p->score=score;
  433.         p->hardlev=c[HARDGAME];     p->suid=userid;
  434.         p->timeused=gtime/100;
  435. # ifndef MAIL           /* dgk */
  436.         p->hasmail = 1;
  437. # endif
  438.         }
  439.     }
  440.  
  441. /*
  442.  *  new2sub(score,i,whoo,whyded)          Subroutine to put player into a 
  443.  *      int score,i,whyded,taxes;         non-winning scoreboard entry if his
  444.  *      char *whoo;                       score is high enough
  445.  *
  446.  *  Enter with the total score in gp in score,  players name in whoo,
  447.  *      died() reason # in whyded, and slot in scoreboard in i.
  448.  *  Returns nothing of value
  449.  */
  450. static new2sub(score,i,whoo,whyded)
  451.     long score;
  452.     int i,whyded;
  453.     char *whoo;
  454.     {
  455.     register int j;
  456.     register struct scofmt *p;
  457.     p = &sco[i];
  458.     if ((score >= p->score) || (c[HARDGAME] > p->hardlev))
  459.         {
  460.         strcpy(p->who,whoo);  p->score=score;
  461.         p->what=whyded;       p->hardlev=c[HARDGAME];
  462.         p->suid=userid;       p->level=level;
  463.         for (j=0; j<26; j++)
  464.             { p->sciv[j][0]=iven[j]; p->sciv[j][1]=ivenarg[j]; }
  465.         }
  466.     }
  467.  
  468. /*
  469.  *  died(x)     Subroutine to record who played larn, and what the score was
  470.  *      int x;
  471.  *
  472.  *  if x < 0 then don't show scores
  473.  *  died() never returns! (unless c[LIFEPROT] and a reincarnatable death!)
  474.  *
  475.  *      < 256   killed by the monster number
  476.  *      256     quit
  477.  *      257     suspended
  478.  *      258     self - annihilated
  479.  *      259     shot by an arrow
  480.  *      260     hit by a dart
  481.  *      261     fell into a pit
  482.  *      262     fell into a bottomless pit
  483.  *      263     a winner
  484.  *      264     trapped in solid rock
  485.  *      265     killed by a missing save file
  486.  *      266     killed by an old save file
  487.  *      267     caught by the greedy cheater checker trap
  488.  *      268     killed by a protected save file
  489.  *      269     killed his family and killed himself
  490.  *      270     erased by a wayward finger
  491.  *      271     fell through a bottomless trap door
  492.  *      272     fell through a trap door
  493.  *      273     drank some poisonous water
  494.  *      274     fried by an electric shock
  495.  *      275     slipped on a volcano shaft
  496.  *      276     killed by a stupid act of frustration
  497.  *      277     attacked by a revolting demon
  498.  *      278     hit by his own magic
  499.  *      279     demolished by an unseen attacker
  500.  *      280     fell into the dreadful sleep
  501.  *      281     killed by an exploding chest
  502.  *      282     killed by a missing maze data file
  503.  *      283     killed by a sphere of annihilation
  504.  *      284     died a post mortem death
  505.  *      285     malloc() failure
  506.  *      300     quick quit -- don't put on scoreboard
  507.  */
  508.  
  509. static int scorerror;
  510. died(x)
  511.     int x;
  512.     {
  513.     register int f,win;
  514.     char ch,*mod;
  515.     long zzz,i;
  516. # ifdef EXTRA
  517.     struct tms cputime;
  518. # endif
  519.     if (c[LIFEPROT]>0) /* if life protection */
  520.         {
  521.         switch((x>0) ? x : -x)
  522.             {
  523.             case 256: case 257: case 262: case 263: case 265: case 266:
  524.             case 267: case 268: case 269: case 271: case 282: case 284:
  525.             case 285: case 300:  goto invalid; /* can't be saved */
  526.             };
  527.         --c[LIFEPROT]; c[HP]=1; --c[CONSTITUTION];
  528.         cursors(); lprcat("\nYou feel wiiieeeeerrrrrd all over! "); beep();
  529.         lflush();  sleep(4);
  530.         return; /* only case where died() returns */
  531.         }
  532. invalid:
  533.     clearvt100();  lflush();  f=0;
  534.     if (ckpflag) unlink(ckpfile);   /* remove checkpoint file if used */
  535. # ifdef MSDOS
  536.     if (swapfd) {
  537.         close(swapfd);
  538.         (void) unlink(swapfile);/* Remove swapfile */
  539.     }
  540.     unsetraw();
  541. # endif
  542.     if (x<0) { f++; x = -x; }   /* if we are not to display the scores */
  543.     if ((x == 300) || (x == 257))  exit();  /* for quick exit or saved game */
  544.     if (x == 263)  win = 1;  else  win = 0;
  545.     c[GOLD] += c[BANKACCOUNT];   c[BANKACCOUNT] = 0;
  546.         /*  now enter the player at the end of the scoreboard */
  547.     newscore(c[GOLD], logname, x, win);
  548.     diedsub(x); /* print out the score line */  lflush();
  549.  
  550.     set_score_output();
  551.     if ((wizard == 0) && (c[GOLD] > 0))     /*  wizards can't score     */
  552.         {
  553.         if (lappend(logfile)<0)  /* append to file */
  554.             {
  555.             if (lcreat(logfile)<0) /* and can't create new log file */
  556.                 {
  557.                 lcreat((char*)0);
  558.                 lprcat("\nCan't open record file:  I can't post your score.\n");
  559.                 sncbr();  resetscroll();  lflush();  exit();
  560.                 }
  561.             chmod(logfile,0666);
  562.             }
  563.         strcpy(logg.who,loginname);
  564.         logg.score = c[GOLD];       logg.diff = c[HARDGAME];
  565.         if (x < 256)
  566.             {
  567.             ch = *monster[x].name;
  568.             if (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u')
  569.                 mod="an";  else mod="a";
  570.             sprintf(logg.what,"killed by %s %s",mod,monster[x].name);
  571.             }
  572.         else sprintf(logg.what,"%s",whydead[x - 256]);
  573.         logg.cavelev=level;
  574.         time(&zzz);   /* get cpu time -- write out score info */
  575.         logg.diedtime=zzz;
  576. #ifdef EXTRA
  577.         times(&cputime);  /* get cpu time -- write out score info */
  578.         logg.cputime = i = (cputime.tms_utime + cputime.tms_stime)/60 + c[CPUTIME];
  579.         logg.lev=c[LEVEL];          logg.ac=c[AC];
  580.         logg.hpmax=c[HPMAX];        logg.hp=c[HP];
  581.         logg.elapsedtime=(zzz-initialtime+59)/60;
  582.         logg.usage=(10000*i)/(zzz-initialtime);
  583.         logg.bytin=c[BYTESIN];      logg.bytout=c[BYTESOUT];
  584.         logg.moves=c[MOVESMADE];    logg.spused=c[SPELLSCAST];
  585.         logg.killed=c[MONSTKILLED];
  586. #endif
  587.         lwrite((char*)&logg,sizeof(struct log_fmt));     lwclose();
  588.  
  589. /*  now for the scoreboard maintenance -- not for a suspended game  */
  590.         if (x != 257)
  591.             {
  592.             if (sortboard())  scorerror = writeboard();
  593.             }
  594.         }
  595.     if ((x==256) || (x==257) || (f != 0)) exit();
  596.     if (scorerror == 0) showscores();   /* if we updated the scoreboard */
  597. # ifdef MAIL
  598.     if (x == 263) mailbill();
  599. # endif
  600.     exit();
  601.     }
  602.  
  603. /*
  604.  *  diedsub(x) Subroutine to print out the line showing the player when he is killed
  605.  *      int x;
  606.  */
  607. static diedsub(x)
  608. int x;
  609.     {
  610.     register char ch,*mod;
  611.     lprintf("Score: %d, Diff: %d,  %s ",(long)c[GOLD],(long)c[HARDGAME],logname);
  612.     if (x < 256)
  613.         {
  614.         ch = *monster[x].name;
  615.         if (ch=='a' || ch=='e' || ch=='i' || ch=='o' || ch=='u')
  616.             mod="an";  else mod="a";
  617.         lprintf("killed by %s %s",mod,monster[x].name);
  618.         }
  619.     else lprintf("%s",whydead[x - 256]);
  620.     if (x != 263) lprintf(" on %s\n",levelname[level]);  else lprc('\n');
  621.     }
  622.  
  623. /*
  624.  *  diedlog()   Subroutine to read a log file and print it out in ascii format
  625.  */
  626. diedlog()
  627.     {
  628.     register int n;
  629.     register char *p;
  630.     struct stat stbuf;
  631.     lcreat((char*)0);
  632.     if (lopen(logfile)<0)
  633.         {
  634.         lprintf("Can't locate log file <%s>\n",logfile);
  635.         return;
  636.         }
  637. #ifdef AMIGA
  638.     if (stat(logfile,&stbuf) < 0)
  639. #else
  640.     if (fstat(fd,&stbuf) < 0)
  641. #endif /* AMIGA */
  642.         {
  643.         lprintf("Can't  stat log file <%s>\n",logfile);
  644.         return;
  645.         }
  646.     for (n=stbuf.st_size/sizeof(struct log_fmt); n>0; --n)
  647.         {
  648.         lrfill((char*)&logg,sizeof(struct log_fmt));
  649.         p = ctime(&logg.diedtime); p[16]='\n'; p[17]=0;
  650.         lprintf("Score: %d, Diff: %d,  %s %s on %d at %s",(long)(logg.score),(long)(logg.diff),logg.who,logg.what,(long)(logg.cavelev),p+4);
  651. #ifdef EXTRA
  652.         if (logg.moves<=0) logg.moves=1;
  653.         lprintf("  Experience Level: %d,  AC: %d,  HP: %d/%d,  Elapsed Time: %d minutes\n",(long)(logg.lev),(long)(logg.ac),(long)(logg.hp),(long)(logg.hpmax),(long)(logg.elapsedtime));
  654.         lprintf("  CPU time used: %d seconds,  Machine usage: %d.%02d%%\n",(long)(logg.cputime),(long)(logg.usage/100),(long)(logg.usage%100));
  655.         lprintf("  BYTES in: %d, out: %d, moves: %d, deaths: %d, spells cast: %d\n",(long)(logg.bytin),(long)(logg.bytout),(long)(logg.moves),(long)(logg.killed),(long)(logg.spused));
  656.         lprintf("  out bytes per move: %d,  time per move: %d ms\n",(long)(logg.bytout/logg.moves),(long)((logg.cputime*1000)/logg.moves));
  657. #endif
  658.         }
  659.         lflush();  lrclose();  return;
  660.     }
  661.  
  662. #ifndef UIDSCORE
  663. /*
  664.  *  getplid(name)       Function to get players id # from id file
  665.  *
  666.  *  Enter with the name of the players character in name.
  667.  *  Returns the id # of the players character, or -1 if failure.
  668.  *  This routine will try to find the name in the id file, if its not there,
  669.  *  it will try to make a new entry in the file.  Only returns -1 if can't
  670.  *  find him in the file, and can't make a new entry in the file.
  671.  *  Format of playerids file:
  672.  *          Id # in ascii     \n     character name     \n   
  673.  */
  674. static int havepid= -1; /* playerid # if previously done */
  675. getplid(nam)
  676.     char *nam;
  677.     {
  678.     int fd7,high=999,no;
  679.     register char *p,*p2;
  680.     char name[80];
  681.     if (havepid != -1) return(havepid); /* already did it */
  682.     lflush();   /* flush any pending I/O */
  683.     sprintf(name,"%s\n",nam);   /* append a \n to name */
  684.     if (lopen(playerids) < 0)   /* no file, make it */
  685.         {
  686.         if ((fd7=creat(playerids,0666)) < 0)  return(-1); /* can't make it */
  687.         close(fd7);  goto addone;   /* now append new playerid record to file */
  688.         }
  689.     for (;;)    /* now search for the name in the player id file */
  690.         {
  691.         p = lgetl();  if (p==NULL) break;   /* EOF? */
  692.         no = atoi(p);   /* the id # */
  693.         p2= lgetl();  if (p2==NULL) break;  /* EOF? */
  694.         if (no>high) high=no;   /* accumulate highest id # */
  695.         if (strcmp(p2,name)==0) /* we found him */
  696.             {
  697.             return(no); /* his id number */
  698.             }
  699.         }
  700.     lrclose();
  701.     /* if we get here, we didn't find him in the file -- put him there */
  702. addone:
  703.     if (lappend(playerids) < 0) return(-1); /* can't open file for append */
  704.     lprintf("%d\n%s",(long)++high,name);  /* new id # and name */
  705.     lwclose();
  706.     lcreat((char*)0);   /* re-open terminal channel */
  707.     return(high);
  708.     }
  709. #endif UIDSCORE
  710.